package com.syh.jn.scm.infrastructure.repository.impl.supplier.sale;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleReturnOrder;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleReturnOrderItem;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleReturnOrderRepository;
import com.syh.jn.scm.dto.supplier.sale.SaleReturnOrderVo;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleReturnOrderItemModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleReturnOrderModel;
import com.syh.jn.scm.infrastructure.repository.utils.MybatisTemplate;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Date:2018/7/17
 * Author:Clown
 * 供应商采购退货的仓储实现;
 */
@Repository
public class SaleReturnOrderRepositoryImpl extends AbstractAggregateRepository<SaleReturnOrder, SaleReturnOrderModel, Long> implements SaleReturnOrderRepository {

  /**
   * 增加
   *
   * @param saleReturnOrder
   * @return
   */
  @Override
  public Long add(SaleReturnOrder saleReturnOrder) {
    Long id = super.add(saleReturnOrder);
    this.saveOrderItems(id, saleReturnOrder.getItems());
    return id;
  }

  /**
   * 修改(也修改了订单项)
   *
   * @param saleReturnOrder
   */
  @Override
  public void update(SaleReturnOrder saleReturnOrder) {
    super.update(saleReturnOrder);
    this.removeItem(saleReturnOrder);
    this.saveOrderItems(saleReturnOrder.getId(), saleReturnOrder.getItems());
  }

  @Override
  public SaleReturnOrder getById(Long id) {
    SaleReturnOrder order = super.getById(id);
    if (order == null) {
      return order;
    }
    order.setItems(this.getItemsBySaleReturnOrderId(id));
    return order;
  }

  /**
   * 修改订单状态(只修改主体)
   *
   * @param saleReturnOrder
   */
  public void updateStatus(SaleReturnOrder saleReturnOrder) {
    super.update(saleReturnOrder);
  }

  /**
   * 删除订单项
   *
   * @param saleReturnOrder
   */
  private void removeItem(SaleReturnOrder saleReturnOrder) {
    StringBuffer hql = new StringBuffer();
    hql.append("from SaleReturnOrderItemModel model where model.saleReturnOrderId = ?");
    List<SaleReturnOrderItemModel> itemModelList = (List<SaleReturnOrderItemModel>) this.hibernateTemplate.find(hql.toString(), saleReturnOrder.getId());
    itemModelList.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  /**
   * 删除
   *
   * @param saleReturnOrder
   */
  @Override
  public void remove(SaleReturnOrder saleReturnOrder) {
    super.removeById(saleReturnOrder.getId());
    this.removeItem(saleReturnOrder);
  }

  /**
   * 保存销售单对应的订单项
   *
   * @param id
   * @param items
   */
  private void saveOrderItems(Long id, List<SaleReturnOrderItem> items) {
    items.stream().forEach(item -> {
      SaleReturnOrderItemModel itemModel = new SaleReturnOrderItemModel();

      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, item.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if (goodsModel.getGoodsBrandId() != null) {
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if (goodsModel.getCategoryId() != null) {
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }
      SaleReturnOrderModel saleReturnOrderModel = this.hibernateTemplate.get(SaleReturnOrderModel.class, id);

      ExtBeanUtils.copyProperties(item, itemModel);
      itemModel.setSaleReturnOrderId(id);
      itemModel.setBusinessEntityId(saleReturnOrderModel.getBusinessEntityId());

      //在仓储层冗余是为了安全和数据的准确
      itemModel.setGoodsName(goodsModel.getName());
      itemModel.setSpecName(goodsModel.getSpecName());
      itemModel.setGoodsCode(goodsModel.getCode());
      itemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      itemModel.setConversionRate(goodsModel.getConversionRate());
      itemModel.setCodeBar(goodsModel.getCodeBar());
      itemModel.setUnits(goodsModel.getUnits());
      itemModel.setCategoryId(goodsModel.getCategoryId());
      itemModel.setCategoryName(goodsCategoryModel.getName());
      itemModel.setCategoryCode(goodsCategoryModel.getCode());
      itemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      itemModel.setBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      itemModel.setBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());

      this.hibernateTemplate.save(itemModel);
    });
  }

  /**
   * 根据销售退货单id获取明细
   *
   * @param id
   * @return
   */
  @Override
  public List<SaleReturnOrderItem> getItemsBySaleReturnOrderId(Long id) {
    String hql = "from SaleReturnOrderItemModel model where model.saleReturnOrderId = ?";
    List<SaleReturnOrderItemModel> itemModelList = (List<SaleReturnOrderItemModel>) this.hibernateTemplate.find(hql, id);
    List<SaleReturnOrderItem> itemList = new ArrayList<>();
    itemModelList.stream().forEach(itemMode -> {
      SaleReturnOrderItem item = new SaleReturnOrderItem();
      ExtBeanUtils.copyProperties(itemMode, item);
      itemList.add(item);
    });
    return itemList;
  }

  /**
   * 根据ids获取明细
   *
   * @param saleReturnOrderIds
   * @return
   */
  @Override
  public List<SaleReturnOrderItem> getItemsBySaleReturnOrderIds(Long[] saleReturnOrderIds) {
    String hql = "from SaleReturnOrderItemModel model where model.saleReturnOrderId in (:saleReturnOrderIds)";

    Query query = buildQuery(hql);
    query.setParameterList("saleReturnOrderIds", saleReturnOrderIds);
    List<SaleReturnOrderItemModel> itemModelList = query.list();
    List<SaleReturnOrderItem> itemList = new ArrayList<>();
    itemModelList.stream().forEach(item -> {
      SaleReturnOrderItem orderItem = new SaleReturnOrderItem();
      ExtBeanUtils.copyProperties(item, orderItem);
      itemList.add(orderItem);
    });

    return itemList;
  }

  /**
   * 上传单据图片
   *
   * @param order
   */
  @Override
  public void uploadImages(SaleReturnOrder order) {
    super.update(order);
  }

  @Override
  public void updateOrderAndItems(SaleReturnOrder order) {
    SaleReturnOrderModel orderModel = this.hibernateTemplate.get(SaleReturnOrderModel.class, order.getId());
    if (orderModel == null) {
      throw new DataModelException("订单不存在");
    }
    ExtBeanUtils.copyProperties(order, orderModel);
    this.hibernateTemplate.update(orderModel);
    //更新订单项
    order.getItems().forEach(orderItem -> {
      SaleReturnOrderItemModel model = this.hibernateTemplate.get(SaleReturnOrderItemModel.class, orderItem.getId());
      if (model == null) {
        throw new DataModelException("对应明细不存在");
      }
      ExtBeanUtils.copyProperties(orderItem, model);
      this.hibernateTemplate.update(model);
    });
  }

  /**
   * 根据服务商id删除订单
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from SaleReturnOrderItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from SaleReturnOrderModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }

  @Override
  protected SQL getViewSql() {
    return new SQL() {{

      SELECT("DISTINCT saleReturnOrder.ID",
              SQLAliasGenerateUtil.aliasGenerate(SaleReturnOrderModel.class, "saleReturnOrder", null),
              "businessEntity.NAME AS businessEntityName,saleOrder.CODE AS saleOrderCode"
      );
      FROM("T_SALE_RETURN_ORDER saleReturnOrder");
      LEFT_OUTER_JOIN("T_SALE_RETURN_ORDER_ITEM item ON item.SALE_RETURN_ORDER_ID = saleReturnOrder.ID");
      LEFT_OUTER_JOIN("T_BASE_DOWNSTREAM businessEntity on saleReturnOrder.DOWN_STREAM_COMPANY_ID = businessEntity.ID",
              "T_SALE_ORDER saleOrder on saleReturnOrder.SALE_ORDER_ID = saleOrder.ID");
    }};
  }

  @Override
  public int getCountView(Wrapper wrapper) {
    StringBuffer sqlSb = new StringBuffer();
    String viewSql = this.getViewSql().toString();

    String viewSqlAry[] = viewSql.split("\\s*FROM\\s*");
    sqlSb.append("SELECT COUNT(DISTINCT saleReturnOrder.ID) AS COUNT FROM ");
    for (int i = 1; i <= viewSqlAry.length - 1; i++) {
      if (i > 1) {
        sqlSb.append(" FROM ").append(viewSqlAry[i]);
      } else {
        sqlSb.append(viewSqlAry[i]);
      }
    }
    BaseResolve resolveToSQL = this.getViewWrapperResolve(wrapper);
    sqlSb.append(" WHERE 1=1 ");
    sqlSb.append(resolveToSQL.resolve());

    Map resultM = MybatisTemplate.selectOne(sqlSb.toString());
    return Integer.parseInt(resultM.get("COUNT").toString());
  }

  @Override
  protected Class getViewObject() {
    return SaleReturnOrderVo.class;
  }

  @Override
  protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
    Map<String, String> params = new HashMap<>();
    params.put("id", "saleReturnOrder.ID");
    params.put("downStreamCompanyId", "saleReturnOrder.DOWN_STREAM_COMPANY_ID");
    params.put("code", "saleReturnOrder.CODE");
    params.put("extCode", "saleReturnOrder.EXT_CODE");
    params.put("name", "businessEntity.NAME");
    params.put("deliName", "saleReturnOrder.DELI_NAME");
    params.put("returnOrdState", "saleReturnOrder.RETURN_ORD_STATE");
    params.put("logisticsCompanyId", "saleReturnOrder.LOGISTICS_COMPANY_ID");
    params.put("deliveryState", "saleReturnOrder.DELIVERY_STATE");
    params.put("collectState", "saleReturnOrder.COLLECT_STATE");
    params.put("inputDateTimestamp", "saleReturnOrder.INPUT_DATE_TIMESTAMP");
    params.put("statementId", "saleReturnOrder.STATEMENT_ID");
    params.put("remark", "saleReturnOrder.REMARK");
    params.put("businessEntityId", "saleReturnOrder.BUSINESS_ENTITY_ID");
    params.put("goodsId", "item.GOODS_ID");
    params.put("goodsName", "item.GOODS_NAME");
    ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
      return params.get(propertyName);
    });
    return parse;
  }

  /**
   * 判断销售退货项是否存在该商品
   *
   * @param column
   * @param id
   * @return
   */
  @Override
  public boolean saleReturnItemExistsById(String column, Long id) {
    StringBuffer hql = new StringBuffer("SELECT COUNT(*) FROM SaleReturnOrderItemModel where ").append(column).append(" = ").append(id);
    this.getLogger().debug(hql.toString());
    Query query = buildQuery(hql);
    return ((Long) query.uniqueResult()).intValue() > 0;
  }
}
